/* 
 * File:   BasicFramework.cpp
 * Author: gilvolpe
 * 
 * Created on March 29, 2013, 6:28 PM
 */

#include "BasicFramework.h"

BasicFramework *BasicFramework::instance = 0;

void BasicFramework::setInstance(BasicFramework* basicFramework) {
    instance = basicFramework;
}

void BasicFramework::handleKeyPressWrapper(unsigned char key, int x, int y) {
    instance->handleKeyPress(key, x, y);
}

void BasicFramework::handleKeyPressWrapperNumber(int key, int x, int y) {
    instance->handleKeyPressNumber(key, x, y);
}

void BasicFramework::displayWrapper() {
    instance->display();
}

void BasicFramework::timerWrapper(GLint unused) {
    instance->timer(unused);
}

void BasicFramework::handleMouseWrapper(GLint state, GLint button, GLint x, GLint y) {
    instance->handleMouse(state, button, x, y);
}

void BasicFramework::handleMouseMotionWrapper(GLint x, GLint y) {
    instance->handleMouseMotion(x, y);
}

void BasicFramework::doSomethingInTimerWrapper() {
    instance->doSomethingInTime();
}

void BasicFramework::timer(GLint unused) {
    doSomethingInTimerWrapper();
    glutPostRedisplay();
    glutTimerFunc(TIME_UPDATE_MS, timerWrapper, unused);
}

void BasicFramework::menuWrapper(int value) {
    instance->menu(value);
}

void jaca(int x) {
    cout << x << endl;
}

void BasicFramework::createMenu() {

    this->subMenuIDADD = glutCreateMenu(this->menuWrapper);
    glutAddMenuEntry("SUN", ADD_SUN);
    glutAddMenuEntry("MER", ADD_MER);
    glutAddMenuEntry("VEN", ADD_VEN);
    glutAddMenuEntry("EAR", ADD_EAR);
    glutAddMenuEntry("MAR", ADD_MAR);
    glutAddMenuEntry("JUP", ADD_JUP);
    glutAddMenuEntry("SAT", ADD_SAT);
    glutAddMenuEntry("URA", ADD_URA);
    glutAddMenuEntry("NET", ADD_NET);

    this->subMenuIDREM = glutCreateMenu(this->menuWrapper);
    glutAddMenuEntry("SUN", REM_SUN);
    glutAddMenuEntry("MER", REM_MER);
    glutAddMenuEntry("VEN", REM_VEN);
    glutAddMenuEntry("EAR", REM_EAR);
    glutAddMenuEntry("MAR", REM_MAR);
    glutAddMenuEntry("JUP", REM_JUP);
    glutAddMenuEntry("SAT", REM_SAT);
    glutAddMenuEntry("URA", REM_URA);
    glutAddMenuEntry("NET", REM_NET);

    //    this->subMenuIDView = glutCreateMenu(this->menuWrapper);
    //    glutAddMenuEntry("SUN", VIEW_SUN);
    //    glutAddMenuEntry("MER", VIEW_MER);
    //    glutAddMenuEntry("VEN", VIEW_VEN);
    //    glutAddMenuEntry("EAR", VIEW_EAR);
    //    glutAddMenuEntry("MAR", VIEW_MAR);
    //    glutAddMenuEntry("JUP", VIEW_JUP);
    //    glutAddMenuEntry("SAT", VIEW_SAT);
    //    glutAddMenuEntry("URA", VIEW_URA);
    //    glutAddMenuEntry("NET", VIEW_NET);

    this->subMenuIDSpaceShip = glutCreateMenu(this->menuWrapper);
    glutAddMenuEntry("ADD SPACESHIP", ADD_SPACESHIP);
    glutAddMenuEntry("DEL SPACESHIP", REM_SPACESHIP);
//    glutAddMenuEntry("VIEW SPACESHIP", VIEW_SPACESHIP);

    int resolvedorDeProblema = glutCreateMenu(this->menuWrapper);

    glutAddSubMenu("ADD GALATIC", this->subMenuIDADD);
    glutAddSubMenu("REM GALATIC", this->subMenuIDREM);
    glutAddSubMenu("VIEW GALATIC", this->subMenuIDView);
    glutAddSubMenu("SPACE SHIP", this->subMenuIDSpaceShip);

    glutAddMenuEntry("QUIT", QUIT);

    glutAttachMenu(GLUT_RIGHT_BUTTON);
}

/*
 * Metodo para deixar o programa em loop
 */
void BasicFramework::start(int argc, char *argv[]) {
    this->printShortcutMenu();
    
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

    glutInitWindowSize(sizeX, sizeY); // definindo o tamanho da tela
    glutCreateWindow("Segundo Trabalho de Computacao Grafica");

    createMenu();

    glutInitWindowPosition(0, 0);

    //Inicializa as funções necessárias ao openGL
    glutDisplayFunc(displayWrapper);
    glutIdleFunc(displayWrapper);
    glutKeyboardFunc(handleKeyPressWrapper);
    glutSpecialFunc(handleKeyPressWrapperNumber);
    glutMouseFunc(handleMouseWrapper);
    glutMotionFunc(handleMouseMotionWrapper);
    glutTimerFunc(TIME_UPDATE_MS, timerWrapper, 0);

    int screen_width = SIDE_SIZE; // We obtain the new screen width values and store it
    int screen_height = SIDE_SIZE; // Height value

    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_SMOOTH);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_COLOR_MATERIAL);

    glEnable(GL_NORMALIZE);

    glViewport(0, 0, screen_width, screen_height);

    glLoadIdentity();

    glEnable(GL_DEPTH_TEST);
    
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    
    glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 
    glEnable(GL_CULL_FACE);
    
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_LIGHTING);

    glutMainLoop();
}

BasicFramework::BasicFramework() {
    this->sizeX = SIDE_SIZE;
    this->sizeY = SIDE_SIZE;
}

BasicFramework::~BasicFramework() {

}

void BasicFramework::printShortcutMenu() {
    cout << "Tabela de Atalhos" << endl;
    cout << "Tecla" << "\t" << "Funcionalidade" << endl;
    cout << "------------------------------------------" << endl;
    cout << "w" << "\t" << "translada espaçonave para frente" << endl;
    cout << "s" << "\t" << "translada espaçonave para trás" << endl;
    cout << "i" << "\t" << "rotaciona espaçonave para cima" << endl;
    cout << "k" << "\t" << "rotaciona espaçonave para baixo" << endl;
    cout << "j" << "\t" << "rotaciona espaçonave no sentido horário" << endl;
    cout << "l" << "\t" << "rotaciona espaçonave no sentido anti-horário" << endl;
    cout << "o" << "\t" << "visualização ortogonal da câmera" << endl;
    cout << "f" << "\t" << "seleciona sombreamento entre Flat e Gouraud" << endl;
    cout << "q" << "\t" << "sair do programa" << endl;
    cout << "<" << "\t" << "translada câmera para a esquerda" << endl;
    cout << ">" << "\t" << "translada câmera para direita" << endl;
    cout << "/\\" << "\t" << "translada câmera para frente" << endl;
    cout << "\\/" << "\t" << "translada câmera para trás" << endl;
}
